package cn.juque.common.aop;

import cn.juque.common.base.BaseResponseDTO;
import cn.juque.common.constants.MessageEnum;
import cn.juque.common.exception.AppException;
import cn.juque.common.thread.BaseOperatorThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import javax.annotation.Resource;

/**
 * @author nuoka
 * @version 1.0.0
 * <li>IntelliJ IDEA</li>
 * <li>cn.juque.cn.juque.common.aop</li>
 * @date 2021/7/25 11:21
 **/
@Slf4j
@Aspect
public class ExceptionAspect {

    @Resource
    private BaseOperatorThreadLocal baseOperatorThreadLocal;

    @Pointcut("@within(cn.juque.common.annotation.HandlerAppException)")
    public void pointcut() {
        // 切面异常
    }

    @Around("pointcut()")
    public Object doAfterThrowing(ProceedingJoinPoint proceedingJoinPoint) {
        try {
            return proceedingJoinPoint.proceed();

        } catch (Throwable throwable) {
            Class<?> clazz = proceedingJoinPoint.getTarget().getClass();
            String methodName = proceedingJoinPoint.getSignature().getName();

            if(throwable instanceof AppException) {
                AppException e = (AppException) throwable;
                return new BaseResponseDTO<>(e.getCode(), e.getMessage());
            }

            log.error("{}#{} error", clazz.getName(), methodName, throwable);
            return new BaseResponseDTO<>(MessageEnum.SYSTEM_ERROR, null);
        } finally {
            if(null != this.baseOperatorThreadLocal) {
                this.baseOperatorThreadLocal.remove();
            }
        }
    }
}
